# -*- coding: utf-8 -*-
# @File  : 迭代器和生成器.py
# @Author: zbh
# @Date  : 2025/4/11_14:31

'''
迭代器是实现了迭代器协议的对象。迭代器协议要求对象必须实现两个方法：__iter__() 和 __next__()。
__iter__() 方法返回迭代器对象本身，它使得对象可以在 for 循环等迭代上下文中使用。
__next__() 方法返回迭代器的下一个值，如果没有更多元素，则抛出 StopIteration 异常。
'''
class MyRange():
    def __init__(self, start, end): # 初始化方法，定义了迭代器的起始和结束位置
        self.start = start
        self.end = end
        self.current = start

    def __iter__(self): # 迭代器方法，返回自身
        return self

    def __next__(self): # 迭代器方法，返回下一个元素
        if self.current < self.end:
            value = self.current
            self.current += 1
            return value
        else:
            raise StopIteration

# 使用自定义迭代器
my_range = MyRange(0, 3) # 创建迭代器对象
print(my_range)
for num in my_range: # 遍历迭代器对象
    print(num)

# 内置迭代器，Python 中有许多内置的迭代器，例如列表、元组、字符串等序列类型都可以通过 iter() 函数转换为迭代器。

l=[1,2,3]
my_iter=iter(l)
print(my_iter)
print(next(my_iter)) # 迭代器对象可以通过 next() 函数获取下一个元素
print(next(my_iter)) # 如果没有更多元素，则抛出 StopIteration 异常
print(next(my_iter))


'''
生成器，是一种特殊的迭代器，创建方式更加简洁，分为：生成器函数和生成器表达式；
1、生成器函数，使用 yield 语句来定义生成器函数，每次调用 next() 函数时，生成器函数会执行到 yield 语句，
并返回一个值，然后暂停执行，直到再次调用 next() 函数。
2、生成器表达式，类似于列表推导式，但是使用圆括号而不是方括号。生成器表达式返回一个生成器对象，
可以通过 for 循环或 next() 函数来遍历生成器对象。
每次调用 next(gen) 时，函数会从上次暂停的地方继续执行，直到遇到下一个 yield 语句。
'''

# 生成器函数
def my_generator(): # 定义生成器函数
    yield 1
    yield 2
    yield 3
# 生成器表达式
my_generator = my_generator() # 创建生成器对象
print(my_generator)
print(next(my_generator)) # 遍历生成器对象
print(next(my_generator))

# 生成器表达式
my_generator = (x for x in range(1, 4)) # 创建生成器对象
print(my_generator)
print(next(my_generator)) # 遍历生成器对象
print(next(my_generator))


'''
生成器与迭代器的区别
创建方式：迭代器需要通过定义类并实现 __iter__() 和 __next__() 方法来创建；而生成器可以通过生成器函数（使用 yield 关键字）或生成器表达式来创建，代码更加简洁。
内存使用：生成器是惰性求值的，只有在需要时才会生成下一个值，因此占用的内存较少；而迭代器可以一次性生成所有的值，可能会占用较多的内存。'''






